Steps in Backpropagation
Backpropagation in Neural Networks
Backpropagation is a cornerstone algorithm for training neural networks. It is based on the simple idea of minimizing the error between the predicted output and the actual output. This is achieved in two primary phases: the forward phase and the backward phase.
1. The Forward Phase
In the forward phase:
- An input-output pair is selected from the training dataset.
- The input nodes of the computational graph (neural network) are fed the attribute values from the selected input.
- Computations are performed in a sequential manner on the network, proceeding from the input layer to the output layer. In directed acyclic graphs (a characteristic of neural networks), we can ensure the correct order by processing nodes in increasing distance from the input nodes.
- Once computations reach the output nodes, the predicted values are obtained.
- If the predicted output values differ from the actual training data output values, an error is computed using a loss function. This quantifies the difference between prediction and reality and gives us a measure of how well the network is performing.
2. The Backward Phase (Backpropagation)
In the backward phase:
- The gradient (or rate of change) of the loss function concerning the weights in the neural network is computed.
- The term "backward" stems from the fact that this computation starts from the output layer and works its way backward to the input layer. The derivatives closer to the output are simpler and computed first. As we move backward, the derivatives become more intricate, and the chain rule of calculus is used extensively.
- These gradients signify how much each weight contributed to the error. Using this information, each weight is adjusted slightly to reduce the error.
3. Weight Update
- The weights are updated in the direction that reduces the loss. Typically, this is achieved by moving the weights in the negative direction of the gradient.
- Learning rates play a critical role here, dictating the size of the steps we take in the direction of the gradient.
The process of forward phase, backward phase, and weight update is repeated for each input-output pair in the training dataset. Once every pair has been used once, we say an epoch has been completed. Training usually involves multiple epochs until the network converges to a satisfactory level of accuracy.
A nuanced aspect of backpropagation is the computation of derivatives of node variables with respect to each other. This is crucial because these derivatives can be used to determine the derivative of the loss function concerning the edge weights. The successive steps in backpropagation allow us to compute these derivatives efficiently, laying the foundation for effective training of neural networks.
Understanding Automatic Differentiation in Computational Graphs
When working with computational graphs, understanding the relationship between nodes and their computations can offer unique insights, especially in the context of differentiation. Let's delve deeper.
Nested Compositions of Functions
It was previously mentioned that one could represent the function of a computational graph in terms of the nodes from the early layers. Such representation would involve nested compositions of functions resulting in a rather cumbersome closed-form expression.
Consider you're trying to describe how a final result is derived by successively applying functions from earlier layers. It's akin to narrating a journey through a multi-layered maze, where each step depends on the one before.
Chain Rule and its Pitfalls
To find the derivative of this nested expression, the chain rule of differential calculus becomes essential. The chain rule allows us to differentiate compositions of functions. However, a naive or "blind" use of this rule would lead us to calculate the derivative of the same expression multiple times because of the repeated compositions. This is both computationally expensive and unnecessary.
Harnessing Structure for Efficiency
Here's where the structure of the computational graph shines. By understanding that some nodes (and their computations) are used repeatedly, we can store intermediate results, thereby avoiding redundant calculations. We can use this stored knowledge to move backward through the graph, computing derivatives starting from the outputs. This approach is reminiscent of dynamic programming, a method used in optimization problems to save computation by storing intermediate results.
In the realm of neural networks, this concept has a special name: backpropagation. Interestingly, while this idea had been explored in the 1960s in the traditional optimization community, the artificial intelligence researchers only started discussing it in the 1980s, coining the term "backpropagation" in the context of neural networks.
The Univariate Chain Rule
The chain rule's essence can be captured in the context of a single-variable function composition. Mathematically, for a function represented as , the chain rule states:
Here, each term on the right is a local gradient, meaning it only considers a small part of the total function, making computation more manageable. The final gradient is then the product of these local gradients.
An Illustrative Example
Consider two functions, and . Their composition results in . Using the univariate chain rule, the derivative is:
Backpropagation in Computational Graphs
In a basic setting, computational graphs present a straightforward representation of calculations, which allows us to visualize how different functions interact with each other. The power of computational graphs lies in their ability to break down complex mathematical operations into simpler components. Especially when dealing with neural networks, understanding the flow of computations can greatly help in the optimization of models. One of the critical aspects of this is the calculation of derivatives, which forms the basis of the backpropagation algorithm.
Understanding the Computational Graph
Consider the example shown in Figure 2.2. Here, the computational graph is a single path. However, in more expressive networks, it is not always the case. A node might feed its output to multiple subsequent nodes. This fan-out scenario complicates the computation of derivatives. With just a single input , if we have computational nodes determining the functions and these nodes link to an output node computing a function with arguments, the overall function becomes . To handle this, the multivariate chain rule comes into play:
Path-centric View of the Chain Rule
An alternative way to look at the multivariate chain rule is through a path-centric perspective. Instead of focusing on nodes, focus on the paths. For any source-sink node pair, applying the multivariate chain rule recursively reveals that the derivative of the variable in the sink node concerning the source node is the sum of expressions originating from the univariate chain rule applied to all paths between those nodes.
This approach, while providing a direct expression for derivatives, does result in redundant calculations. This is particularly evident when there are many paths between a node pair. The number of these paths can grow exponentially with the path length. This kind of repetition becomes a performance concern in large multilayer networks with shared nodes, as functions might be differentiated multiple times.
An example of this can be observed with the simple function as depicted in Figure 2.4. Here, the multivariate chain rule gives the derivative of output with respect to :
Which simplifies to:
Such examples emphasize the importance of understanding the computational graph's structure to avoid redundancies during the differentiation process.
Pathwise Aggregation
The path-centric perspective of the multivariate chain rule can be summarised:
For a directed acyclic computational graph where the node contains the variable , the local derivative of the directed edge is defined as . Given a set of paths from node to node in the graph, the value of is given by computing the product of local gradients along each path in and summing these products over all paths in .
Understanding the Computational Graph Equations
Number of Paths and Hidden Units
The number of paths between the input and the output in the computational graph grows exponentially. Specifically, for the provided case:
This implies that the computational graph has five layers, with each layer having two units, hence giving rise to 32 different paths between the input and output.
The jth
hidden unit of the ith
layer is symbolized as . The function for each of these hidden units is defined by:
This equation indicates that each hidden unit is the product of its two preceding nodes.
Differentiation and Output
In the context presented, the output is given by:
Although this output is straightforward to differentiate with respect to x
directly, the exponential-time algorithm can be employed to gain insights into its operational dynamics.
Derivatives of Hidden Units
For each hidden unit , the partial derivatives with respect to its two inputs are:
These equations reveal an interesting property: the partial derivative of a multiplication operation with respect to one of the variables is the other variable.
THIS NEEDS FIXING BUT YOU NEED TO FIND OUT HOW TO FIX THE EQUATION IN LATEX!!!
Derivative with Respect to Input x
The derivative of the output o
with respect to the input x
can be obtained by summing the products of local derivatives along all 32 paths from the input to the output:
Given the properties of the computational graph and its derivatives, this can be simplified to:
The result is consistent with directly differentiating the function with respect to x
.
Explaining Path-Aggregative Values in Graph Theory
In graph theory, computing all types of path-aggregative values over directed acyclic graphs is done using dynamic programming. Consider a directed acyclic graph in which the value (interpreted as local partial derivative of variable in node j
with respect to variable in node i
) is associated with edge . In other words, if is the variable in the node p
, we have the following:
An example of such a computational graph is shown in Figure. In this case, we have associated the edge with the corresponding partial derivative. We would like to compute the product of over each path from source node s
to output node t
and then add them in order to obtain the partial derivative:
Let be the set of nodes at the end points of outgoing edges from node i
. We can compute the aggregated value for each intermediate node i
(between source node s
and output node t
) using the following well-known dynamic programming update:
This computation can be performed backwards starting from the nodes directly incident on o
, since is already known to be 1. This is because the partial derivative of a variable with respect to itself is always 1. Therefore one can describe the pseudocode of this algorithm as follows:
- Initialize
- repeat
- Select an unprocessed node
i
such that the values of for all of its outgoing nodes are available. - Update
- Select an unprocessed node
- until all nodes have been selected;